package controller

import (
	apiserver "apedge/apiserver"
	"apedge/dto"
	"apedge/pkg/configs"
	"io"

	"github.com/gin-gonic/gin"
)

func ApedgeNodeRouter(r *gin.Engine) {
	group := r.Group("/api/v1/apedge/node")

	group.GET("", dto.Wrapper(GetNodeList))
	group.GET("/:nodeId", dto.Wrapper(GetNodeDetail))
	group.POST("", dto.Wrapper(CreateNode))
	group.DELETE("/:nodeId", dto.Wrapper(DelNode))

	group.GET("/nodeType", dto.Wrapper(GetNodeType))
	group.GET("/nodeArchType", dto.Wrapper(GetArchType))
	group.POST("/certificate/:nodeId", dto.Wrapper(CreateNodeCertificate))
	group.GET("/scripts", dto.Wrapper(GetInstallScripts))
	group.GET("/offline", dto.Wrapper(NodeOffline))
	group.GET("/download/:nodeId", dto.Wrapper(GetNodeCertificate))
	group.GET("/health/ping", dto.Wrapper(Health))
}

func CreateNode(c *gin.Context) error {
	var err error
	var req dto.CreateNodeReq
	var rsp dto.CreateNodeRsp

	err = c.ShouldBindJSON(&req)
	if err != nil {
		return dto.ParameterError(c, err.Error())
	}
	userInfo, errRsp := PreHandler(c, &req)
	
	if errRsp != nil {
		return errRsp
	}

	nodeId, err := apiserver.CreateNode(req, userInfo)
	if err != nil {
		logger.Errorln(err)
		return dto.ErrorToCodeRsp(c, err)
	}

	rsp = dto.CreateNodeRsp{
		NodeId: nodeId,
	}
	return dto.SuccessResp(c, rsp)
}

func GetNodeList(c *gin.Context) error {
	var req dto.GetNodeListReq
	var rsp dto.GetNodeListRsp
	var err error

	var list []dto.OutApedgeNodeItem
	var count int64

	err = c.ShouldBindQuery(&req)
	if err != nil {
		return dto.ParameterError(c, err.Error())
	}
	userInfo, errRsp := PreHandler(c, &req)
	if errRsp != nil {
		return errRsp
	}

	list, count, err = apiserver.GetNodeList(req, userInfo)
	if err != nil {
		return dto.ErrorToCodeRsp(c, err)
	}

	rsp = dto.GetNodeListRsp{
		Items: list,
		Total: count,
	}
	return dto.SuccessResp(c, rsp)
}

func GetNodeDetail(c *gin.Context) error {
	var err error
	var req dto.GetNodeDetailReq
	var rsp dto.GetNodeDetailRsp

	idStr := c.Param("nodeId")
	if idStr == "" {
		return dto.ParameterError(c, "need nodeId")
	}

	_, errRsp := PreHandler(c, &req)
	if errRsp != nil {
		return errRsp
	}
	out, err := apiserver.GetNodeDetail(idStr)
	if err != nil {
		return dto.ErrorToCodeRsp(c, err)
	}

	rsp = dto.GetNodeDetailRsp{
		OutApedgeNodeItem: *out,
	}
	return dto.SuccessResp(c, rsp)
}

func DelNode(c *gin.Context) error {
	var err error
	var req dto.DelNodeReq
	var rsp dto.DelNodeRsp

	idStr := c.Param("nodeId")
	if idStr == "" {
		return dto.ParameterError(c, "need nodeId")
	}
	_, errRsp := PreHandler(c, &req)
	if errRsp != nil {
		return errRsp
	}

	err = apiserver.DelNode(idStr)
	if err != nil {
		return dto.ErrorToCodeRsp(c, err)
	}

	return dto.SuccessResp(c, rsp)
}

func GetNodeType(c *gin.Context) error {
	rsp := dto.NodeTypeRsp{
		Types: configs.Config.Relevant.NodeInfo.NodeType,
	}
	return dto.SuccessResp(c, rsp)
}

func CreateNodeCertificate(c *gin.Context) error {
	var err error
	var req dto.CreateNodeCertReq
	var rsp dto.CreateNodeCertRsp
	err = c.ShouldBindUri(&req)
	if err != nil {
		return dto.ParameterError(c, err.Error())
	}

	userInfo, errRsp := PreHandler(c, &req)
	if errRsp != nil {
		return errRsp
	}

	err = apiserver.CreateEdgeNodeCert(userInfo, req.NodeId)
	if err != nil {
		return dto.ErrorToCodeRsp(c, err)
	}

	return dto.SuccessResp(c, rsp)
}

func GetInstallScripts(c *gin.Context) error {
	var err error
	var req dto.GetInstallScriptReq

	err = c.ShouldBindQuery(&req)
	if err != nil {
		return dto.ParameterError(c, err.Error())
	}
	userInfo, errRsp := PreHandler(c, &req)
	if errRsp != nil {
		return errRsp
	}

	scripts, err := apiserver.GetInstallScripts(req, userInfo)
	if err != nil {
		logger.Errorln(err)
		return dto.ErrorToCodeRsp(c, err)
	}

	data := dto.GetInstallScriptRsp{
		Script: scripts,
	}
	return dto.SuccessResp(c, data)
}

func Health(c *gin.Context) error {
	data := make(map[string]string)
	data["data"] = "ok"
	return dto.SuccessResp(c, data)
}

func GetArchType(c *gin.Context) error {
	rsp := dto.ListArchTypeRsp{
		Types: configs.Config.Relevant.NodeInfo.NodeArchType,
	}
	return dto.SuccessResp(c, rsp)
}

func GetNodeCertificate(c *gin.Context) error {
	var err error
	var req dto.GetNodeCertificateReq

	err = c.ShouldBindUri(&req)
	if err != nil {
		return dto.ParameterError(c, err.Error())
	}

	userInfo, errRsp := PreHandler(c, &req)
	if errRsp != nil {
		return errRsp
	}
	f, _, err := apiserver.GetNodeCertificate(req, userInfo)
	if err != nil {
		logger.Errorln(err)
		return dto.ErrorToCodeRsp(c, err)
	}
	c.Writer.Header().Add("Content-type", "application/octet-stream")
	_, err = io.Copy(c.Writer, f)
	if err != nil {
		logger.Errorln(err)
		return dto.ErrorToCodeRsp(c, err)
	}

	// err = os.Remove(packagePath)
	if err != nil {
		logger.Errorln(err)
		return dto.ErrorToCodeRsp(c, err)
	}
	return nil
}

func NodeOffline(c *gin.Context) error {
	rsp := dto.NodeOfflineRsp{
		Data: "sudo bash /opt/apulisedge/uninstall_edge.sh",
	}
	return dto.SuccessResp(c, rsp)
}
